<?php
namespace hc;
class tpl{
	private $vars=array();
	private $tpl_left;
	private $tpl_right;
	private $tpl_cache_html;//静态缓存
	private $default_cache_compile;//配置编译缓存;默认设置
	private $default_cache_html;//配置静态静态缓存，默认设置
	private $default_html_time;//默认静态缓存时间
	private $tpl_suffix;
	private $tpl_cache_compile_dir;
	private $tpl_cache_html_dir;
	private $tpl_filename;//模版地址文件
  private $tag_foreach = array('from', 'item', 'key');//定义foreach b标签

    public function __construct(){
		$tpl_left=str_split(C('tpl_left'));
		$tpl_right=str_split(C('tpl_right'));
		$this->tpl_left='\\'.implode('\\',$tpl_left);
		$this->tpl_right='\\'.implode('\\',$tpl_right);
		$this->tpl_suffix=C('tpl_suffix');
		$this->tpl_cache_compile_dir=CACHE_PATH_COMPILE;//编译缓存目录
		$this->tpl_cache_html_dir=CACHE_PATH_HTML;//静态缓存目录
		$this->default_cache_compile=C('tpl_cache_compile');
		$this->default_cache_html=C('tpl_cache_html');
		$this->default_html_time=C('tpl_html_time');
		$this->tpl_cache_html=false;
		$this->hc_tpl=HC_TPL."/".$_REQUEST['g']."/";
		load_helpers('mysqllog');
		$this->assign('baseurl',BASE_URL);
		$this->assign('modelurl',MODEL_URL);
		$this->assign('ctlurl',CTL_URL);
		$this->assign('mothedurl',MOTHED_URL);
	}
	//编译缓存状态设置
	protected function setCompileType($type=false){
		$this->default_cache_compile=$type;
	}
	//静态缓存状态设置
	protected function setCacheType($type=false){
		$this->tpl_cache_html=$type;
	}
	//静态缓存时间设置
	protected function setCacheTime($time){
		$this->default_html_time=$time;
	}
	//默认模版
	private function default_tpl($html){
		$this->tpl_filename=$this->hc_tpl.$html;
		if(!is_file($this->tpl_filename)){
			msg_error('模版文件'.$this->tpl_filename."不存在");exit;
		}
	}
	//是否有静态缓存
	protected function isCacheType($html){//false 无 true有
		if($this->default_cache_html && $this->tpl_cache_html){
			$this->default_tpl($html);
			return $this->get_html_cache()!==false?true:false;
		}else{
			return false;
		}
	}
	//是否有编译缓存
	protected function isCompileType($html){
		if($this->default_cache_compile){
			$this->default_tpl($html);
			return $this->get_compile_chahe()!==false?true:false;
		}
		return false;
	}

	public function assign($key,$val){
		$this->vars[$key]=$val;
	}
	//$cache_time=false;不存在静态缓存。则调用缓存
	public function display($html=''){
		$this->default_tpl($html);//设置默认html文件地址
		if($this->tpl_cache_html && $this->default_cache_html && $this->default_cache_compile){//开启静态缓存和 编译缓存
			if(($content=$this->get_html_cache())!==false){//判断是否存在静态缓存
				echo $content;exit;
			}elseif(($content=$this->get_compile_chahe())!==false){//判断是否存在编译缓存
				 $content=$this->set_html_cache();//存在编译缓存。不存在静态缓存;
				 echo $content;exit;
			}else{//不存在编译缓存 和静态缓存
				$content=$this->set_compile_cache();
				$content=$this->set_html_cache($content);
				echo $content;exit;
			}
		}elseif($this->tpl_cache_html && $this->default_cache_html){//存在静态缓存， 不存在编译缓存
			if(($content=$this->get_html_cache())!==false){//判断是否存在静态缓存
				echo $content;exit;
			}else{//不存在静态缓存
				$content=$this->set_html_cache();//创建静态缓存
				echo $content;exit;
			}
		}elseif($this->default_cache_compile){//不存在静态缓存，存在编译缓存
			if(($content=$this->get_compile_chahe())!==false){//判断是否存在编译缓存
				$content=$this->parse_php($content);
				echo $content;exit;
			}else{//不存在编译缓存
				$content=$this->set_compile_cache();//在开启编译缓存情况下。创建编译缓存
				$content=$this->parse_php($content);
				echo $content;exit;
			}
		}else{//不存在静态缓存和编译缓存
			$content=$this->read_file($this->tpl_filename);//打开文件获取内容
			$content=$this->parse($content);
			$content=$this->parse_php($content);
			echo $content;exit;
		}
	}
	//静态缓存文件名
	public function get_html_filename(){
		return $this->tpl_cache_html_dir."/html_".md5($this->tpl_filename).$this->tpl_suffix;
	}
	//编译缓存文件名
	public function get_compile_filename(){
		return $this->tpl_cache_compile_dir."/compile_".md5($this->tpl_filename).$this->tpl_suffix;//编译缓存文件名
	}
	//编译缓存
	private function get_compile_chahe(){
		$compilefile=$this->get_compile_filename();
		if(is_file($compilefile)){
			$cahce_content=file_get_contents($compilefile);
			$cache_arr=unserialize($cahce_content);
			$md5file=md5_file($this->tpl_filename);//对文件内容进行哈希加密
			if($md5file!=$cache_arr['md5file']){
				//模版文件被修改 重新生成编译文件
				return false;
			}else{
				return $cache_arr['content'];
			}
		}else{
			return false;
		}
	}
	//静态缓存
	private function get_html_cache(){
		$htmlfilename=$this->get_html_filename();
		if(is_file($htmlfilename)){
			$cache_html_content=file_get_contents($htmlfilename);
			$cache_html_arr=unserialize($cache_html_content);
			$end_time=$cache_html_arr['cache_time'];
			if($end_time<=time()){
				return false;
			}else{
				return $cache_html_arr['content'];//存在静态内容
			}
		}else{
			return false;
		}
	}
	//生成编译缓存
	private function set_compile_cache(){
		$compilefile=$this->get_compile_filename();
		$content=$this->read_file($this->tpl_filename);//打开文件获取内容
		$content=$this->parse($content);
		$cahce_arr['md5file']=md5_file($this->tpl_filename);//判断是否文件被修改
		$cahce_arr['mtime']=time();
		$cahce_arr['content']=$content;
		$cahce_content=serialize($cahce_arr);
		$return=file_put_contents($compilefile,$cahce_content);
		if($return<=0){
			msg_error('生成编译缓存文件失败');
		}
		return $content;

	}
	//生成静态缓存
	private function set_html_cache($compile_content=false){
		if($compile_content!==false){
			$content=$this->parse_php($compile_content);
		}else{
			$content=$this->read_file($this->tpl_filename);//打开文件获取内容
			$content=$this->parse($content);
			$content=$this->parse_php($content);
		}
		$cache_html_arr['mtime']=time();
		$cache_html_arr['content']=$content;
		$cache_html_arr['cache_time']=time()+$this->default_html_time;
		$cache_html_content=serialize($cache_html_arr);
		$return=file_put_contents($this->get_html_filename(),$cache_html_content);
		if($return>0){
			return $content;
		}else{
			msg_error("写入静态数据失败");
		}
	}
	/**
     *  读文件
     *  @param  string  $path   文件完整路径
     *  @return 模板内容
     */
    private function read_file($path) {
		if(!is_file($path)){
			msg_error($path."模版文件不存在");exit;
		}
        if(($r = @fopen($path, 'r')) === false) {
           msg_error('模版文件没有读取或执行权限，请检查！');exit;
        }
        $content = fread($r,filesize($path));
        fclose($r);
        return $content;
    }
	/**
     *  开始解析相关模板标签
     * @param $content 模板内容
     */
    private function parse($content) {
		if(empty($content)) return false;
		//include 现在最多支持两次；
        $content = $this->parse_include($content);
        //如果包含文件存在include();则再次include处理
        $content = $this->parse_include($content);
		//foreach
		$content=$this->parse_foreach($content);

		 //if
        $content = $this->parse_if($content);

        //elseif
        $content = $this->parse_elseif($content);

		//常量com 和 变量
		$content=$this->parse_com($content);
        return $content;
    }
    //原生php 解析
    private function parse_php($content)
    {
    	ob_start();
    	ob_implicit_flush(0);
    	echo eval('?>'.$content);
    	$content = ob_get_contents();
    	ob_end_clean();
    	return $content;
    }
	/**
	 *include解析
	 * {include(home/login.html)}
	 */
	private function parse_include($content){
		$p="/".$this->tpl_left."include\(([^)]*)\)".$this->tpl_right."/is";
		preg_match_all($p,$content,$include_arr);
		if(empty($include_arr[0])){

			return $content;
		}

		foreach($include_arr[1] as $k=>$v){
			$include_filepath=$this->hc_tpl.$include_arr[1][$k];

			$include_content=$this->read_file($include_filepath);
			$content=str_replace($include_arr[0][$k],$include_content,$content);
		}
        return $content;
	}
	/**
	 * 公共解析 ，常量解析，变量解析等
	 */
	private function parse_com($content){

	// 如常量：{__INDEX__}
		$content=preg_replace("/".$this->tpl_left."(\_\_\w*\_\_)".$this->tpl_right."/","<?= $1;?>",$content);
		//{key}变量
		$content=preg_replace("/".$this->tpl_left."(\w*)".$this->tpl_right."/","<?= \$this->vars['$1'];?>",$content);

		//数组的替换 支持一维数组{vo.name}
		$preg = '/'.$this->tpl_left.'(\w*)\.(\w*)'.$this->tpl_right.'/';
		$content= preg_replace($preg,"<?=\$this->vars['$1']['$2']?>",$content);

		//数组的替换 支持一维数组{}
		$preg = '/'.$this->tpl_left.'\\$(\w*)\.(\w*)'.$this->tpl_right.'/';
		$content = preg_replace($preg,"<?=$$1['$2']?>",$content);

		//{$key}变量
		$content=preg_replace("/".$this->tpl_left."\\$(\w*)".$this->tpl_right."/","<?=$$1;?>",$content);

		//foreach if else 结束
		$search = array(
            "/".$this->tpl_left."\/foreach".$this->tpl_right."/is",
            "/".$this->tpl_left."\/if".$this->tpl_right."/is",
            "/".$this->tpl_left."\/else".$this->tpl_right."/is",

        );
        $replace = array(
            "<?php } ?>",
            "<?php } ?>",
            "<?php } else { ?>"
        );
        $content = preg_replace($search, $replace, $content);
		return $content;
	}
	/**
     * 解析 foreach
     * 使用方法 {foreach from=$lists item=value key=kk}
     * @param $content 模板内容
     * @return html 解析后的内容
     */
    private function parse_foreach($content) {
      	preg_match_all("/".$this->tpl_left."foreach\s+(.*?)".$this->tpl_right."/is",$content,$match);

        if(!isset($match[1]) || !is_array($match[1])) return $content;
        foreach($match[1] as $match_key => $value) {
            $split = preg_split("/\s+/is", $value);//匹配空字符
            $split = array_filter($split);
            $new_tag = array();
            foreach($split as $v) {
                $a = explode("=", $v);
                if(in_array($a[0], $this->tag_foreach)) {//此处过滤标签 不存在过滤
                    $new_tag[$a[0]] = $a[1];
                }
            }
            $key = '';

			extract($new_tag);
            $key = ($key) ? '$'.$key.' =>' : '' ;

			$from="\$this->vars['$from']";

            $s = '<?php foreach('.$from.' as '.$key.' $'.$item.') { ?>';

            $content =str_replace($match[0][$match_key], $s, $content);
        }

        return $content;
    }
	 /**
     * if判断语句
     * <{if empty($zhang)}>
     * zhang
     * <{elseif empty($liang)}>
     *  liang
     * <{else}>
     *  zhangliang
     * <{/if}>
     */
    private function parse_if($content) {
        preg_match_all("/".$this->tpl_left."if\s+(.*?)".$this->tpl_right."/is", $content, $match);
        if(!isset($match[1]) || !is_array($match[1])) return $content;
        foreach($match[1] as $k => $v){
            //$s = preg_split("/\s+/is", $v);
            //$s = array_filter($s);
            $content = str_replace($match[0][$k], "<?php if($v) { ?>", $content);
        }

        return $content;
    }


	/**
     * 解析 else if
     * 使用方法
     * @param $content 模板内容
     * @return html 解析后的内容
     */
	 private function parse_elseif($content) {
        preg_match_all("/".$this->tpl_left."\/elseif\s+(.*?)".$this->tpl_right."/is",$content,$match);
        if(!isset($match[1]) || !is_array($match[1])) return $content;

        foreach($match[1] as $k => $v) {
            //$s = preg_split("/\s+/is", $v);
            //$s = array_filter($s);
            $content = str_replace($match[0][$k], "<?php } elseif ({$v}) { ?>", $content);
        }

        return $content;
    }
}
/*生成静态缓存
public function index(){
	$this->setCacheType(1);
	if($this->isCacheType('hadmin/index.tpl')===false){
		数据查询
	}
	$this->display('hadmin/index.tpl');
}*/

/*
$arr=array(
	0=>array('id'=>1,'name'=>'name1'),
	1=>array('id'=>2,'name'=>'name2'),
	2=>array('id'=>3,'name'=>'name3')
);
$list_array=array('id'=>1);
$result->assign('item',array(1,3,5,6,7));
$result->assign("arr",$arr);
$result->assign("arr_list",$list_array);
$result->display('index');*/

/*模板htmlhtml 文件
 {foreach from=lists item=value key=kk}
{/foreach}
1种i情况
if{$this->vars[list] ==1}//一维z数组
2种情况
{if $val['id']}y使用余foreach中
*/
?>
